#include "IRender.h"

struct MouseBallRender : IRender
{
	const float radius = 50.0f;

	MouseBallRender(const dxres& res) :
		IRender(res)
	{
	}

	void Render() override
	{
		D2D1_SIZE_F size = m_res.target->GetSize();

		D2D1_RECT_F rect = RectF(0.0f, 0.0f, 
								 size.width, size.height);

		D2D1_ELLIPSE ellipse = Ellipse(GetPhysicalCursor(),
									   radius, 
									   radius);

		m_res.target->FillEllipse(ellipse, m_brush.Get());
	}

	D2D1_POINT_2F GetPhysicalCursor()
	{
		POINT p;
		VERIFY(GetCursorPos(&p));
		VERIFY(ScreenToClient(m_res.window, &p));
		
		D2D1_POINT_2F cursor = Point2F(PhysicalToLogical(p.x, m_res.dpi), 
									   PhysicalToLogical(p.y, m_res.dpi));

		return cursor;
	}

	void CreateDeviceResources()
	{
		CreateBrush(GetPhysicalCursor());
	}

	void CreateBrush(D2D1_POINT_2F cursor)
	{
		D2D1_GRADIENT_STOP stops[] = 
		{
			GradientStop(0.0f, ColorF(ColorF::White)), 
			GradientStop(1.0f, ColorF(ColorF::LightYellow, 0.0f))
		};

		ComPtr<ID2D1GradientStopCollection> collection;

		HR(m_res.target->CreateGradientStopCollection(stops, 
													  _countof(stops), 
													  collection.GetAddressOf()));

		auto properties = RadialGradientBrushProperties(Point2F(cursor.x, cursor.y), 
														Point2F(), 
														radius, 
														radius);

		HR(m_res.target->CreateRadialGradientBrush(properties, 
												   collection.Get(), 
												   m_brush.ReleaseAndGetAddressOf()));
	}

	void ReleaseDeviceResources() override
	{
		m_brush.Reset();
	}

	void OnMouseMove(LPARAM const lparam)
	{
		if (IsDeviceCreated())
		{
			D2D1_POINT_2F point = Point2F(PhysicalToLogical(LOWORD(lparam), m_res.dpi), 
										  PhysicalToLogical(HIWORD(lparam), m_res.dpi));
			CreateBrush(point);
		}
	}

	LRESULT MessageHandler(UINT const message, WPARAM const wparam, LPARAM const lparam)
	{
		if (message == WM_MOUSEMOVE)
		{
			OnMouseMove(lparam);
		}

		return 0;
	}

	ComPtr<ID2D1RadialGradientBrush> m_brush;
};